Back dirty and deleted SObject collections by a Map<Id, SObject>

Currently fflib_SObjectUnitOfWork uses a List<SObject> to maintain the collections of objects to be updated or deleted. Records are added to these collections by calling registerDirty and registerDeleted, respectively. This pull request makes a change to use a Map<Id, SObject> to maintain the collections of dirty and deleted objects. This allows daisy chaining of operations on the same collection of objects, without registering the same object more than once (thus causing a DMLException at commit time). Consider the following class that implements fflib_SObjectDomain:
```
public class MyCustomObjects extends fflib_SObjectDomain {
	
	public MyCustomObjects(List<MyCustomObject__c> sObjectList) {
		super(sObjectList);
	}
	
	public class Constructor implements fflib_SObjectDomain.IConstructable {
		public fflib_SObjectDomain construct(List<SObject> sObjectList) {
			return new MyCustomObjects(sObjectList);
		}
	}
	
	public void setCurrency1(fflib_SObjectUnitOfWork uow) {
		for (MyCustomObject__c mco : (List<MyCustomObject__c>) this.Records) {
			if (!String.isBlank(mco.Text1__c)) {
				mco.Currency1__c = 100.00;
				if (mco.Id != null) {
					uow.registerDirty(mco);
				}
			}
		}
	}
	
	public void setCurrency2(fflib_SObjectUnitOfWork uow) {
		for (MyCustomObject__c mco : (List<MyCustomObject__c>) this.Records) {
			if (!String.isBlank(mco.Text2__c)) {
				mco.Currency2__c = 200.00;
				if (mco.Id != null) {
					uow.registerDirty(mco);
				}
			}
		}
	}
}
```

The following unit test will fail with a "Duplicate Id" exception during the commit work phase with the current, List backed implementation of fflib_SObjectUnitOfWork:

```
	static testMethod void myUnitTest() {
		List<MyCustomObject__c> mcoList = new List<MyCustomObject__c>();
		mcoList.add(new MyCustomObject__c(Text1__c = 'Non-blank'));
		mcoList.add(new MyCustomObject__c(Text2__c = 'Non-blank'));
		mcoList.add(new MyCustomObject__c(Text1__c = 'Non-blank', Text2__c = 'Non-blank'));
		insert mcoList;
		
		fflib_SObjectUnitOfWork uow = new fflib_SObjectUnitOfWork(new Schema.SObjectType[] { MyCustomObject__c.SObjectType });
		MyCustomObjects mcoDomain = new MyCustomObjects(
			[SELECT Id, Name, Text1__c, Text2__c, Currency1__c, Currency2__c FROM MyCustomObject__c ORDER BY Name ASC]
		);
		mcoDomain.setCurrency1(uow);
		mcoDomain.setCurrency2(uow);
		uow.commitWork();
		
		mcoList = [SELECT Id, Name, Text1__c, Text2__c, Currency1__c, Currency2__c FROM MyCustomObject__c ORDER BY Name ASC];
		for (MyCustomObject__c mco : mcoList) {
			if (!String.isBlank(mco.Text1__c)) {
				System.assertEquals(100, mco.Currency1__c);
			} else {
				System.assertEquals(null, mco.Currency1__c);
			}
			
			if (!String.isBlank(mco.Text2__c)) {
				System.assertEquals(200, mco.Currency2__c);
			} else {
				System.assertEquals(null, mco.Currency2__c);
			}
		}
	}
```
The failure occurs because the third instance of MyCustomObject__c is registered as dirty twice. Running the same unit test using the Map backed collection of dirty objects passes.