docs: function Model(value) {
                  var instance = this,
                      commits = [];
  
                  // if the value is undefined, create a empty obj
                  value = value || {};
  
                  // build the defaults but only on new instances
                  forEach(options.defaults, function(v, k){
                      // only populates when not already defined
                      if(value[k] === undefined){
                          if(typeof v === 'function'){
                              // pass the value so you can combine things
                              // this could be tricky if you have defaults that rely on other defaults ...
                              // like: { name: function(val) { return val.firstName + val.lastName }) }
                              value[k] = copy(v(value));
                          } else {
                              value[k] = copy(v);
                          }
                      }
                  });
  
                  // Map all the objects to new names or relationships
                  forEach(options.map, function(v, k){
                      if (functionName(v) === functionName(Model) || functionName(v) === functionName(ModelCollection)) {
                          value[k] = new v(value[k]); // jshint ignore:line
                      } else if (typeof v === 'function') {
                          // if its a function, invoke it,
                          // this would be helpful for seralizers
                          // like: map: { date: function(val){ return moment(val) } }
                          value[k] = v(value[k], value);
                      } else {
                          value[k] = value[v];
                          delete value[v];
                      }
                  });
  
                  // attach instance actions
                  forEach(options.actions, function(v, k){
                      if(k[0] === '$'){
                          instance[k] = function(){
                              return Model.$buildRequest(k, v, instance);
                          };
                      }
                  });
  
                  // copy values to the instance
                  extend(instance, value);
  
                  // copy instance level helpers to this instance
                  extend(instance, copy(options.instance));
  
                  /**
                   * Save the instance to the server.  Posts the instance unless
                   * the instance has the `pk` attribute already then it will do a put.
                   */
                  instance.$save = function(){
                       var actionType = instance[options.pk] ? 'update' : 'post',
                           promise = Model[actionType](this);
  
                      instance.$pending = true;
  
                      promise.then(function(value){
                          instance.$pending = false;
  
                          // extend the value from the server to me
                          if (value) {
                              instance.$update(value);
                          }
  
                          var broadcastName = actionType === 'post' ? 'created' : 'updated';
                          $rootScope.$broadcast(prettyName + '-' + broadcastName, instance);
  
                          // commit the change for reversion
                          commits.push(angular.toJson(instance));
                      }, function () {
                          // rejected
                          instance.$pending = false;
                      });
  
                      return promise;
                  };
  
                  /**
                   * Delete the instance.  Performs a DELETE on this instance performing
                   * the delete action passing an instance of itself.
                   *
                   * If the item is associated with an array, it will automatically be removed
                   * on successful delete.
                   */
                  instance.$destroy = function(){
                      // keep a local pointer since we strip before send
  
                      var promise = Model.delete(this);
                      instance.$pending = true;
  
                      promise.then(function(){
                          instance.$pending = false;
  
                          var arr = instance.$$array;
                          if(arr){
                              arr.splice(arr.indexOf(instance), 1);
                          }
  
                          $rootScope.$broadcast(prettyName + '-destroyed', instance);
                      }, function(){
                          // rejected
                          instance.$pending = false;
                      });
  
                      return promise;
                  };
  
                  /**
                   * Display the difference between the original data and the
                   * current instance.
                   * https://github.com/flitbit/diff
                   */
                  instance.$diff = function(version){
                      var prevCommit = commits[version || commits.length - 1],
                          currCommit = angular.toJson(instance);
  
                      return DeepDiff.diff(JSON.parse(prevCommit), JSON.parse(currCommit), function(path, key) {
                          return key[0] === '$';
                      });
                  };
  
  
                  /**
                   * Commits the change the commits bucket for rollback later if needed.
                   */
                  instance.$commit = function () {
                      // stringify it so you have a clean instance
                      commits.push(angular.toJson(instance));
                      return instance;
                  };
  
                  /**
                   * Reverts the current instance back either the latest instance
                   * or you can pass a specific instance on the commits stack.
                   */
                  instance.$rollback = function(version) {
                      var prevCommit = commits[version || commits.length - 1];
                      instance.$update(JSON.parse(prevCommit));
                      return instance;
                  };
  
                  /**
                   * Extends the properties of the new object onto
                   * the current object without replacing it.  Helpful
                   * when copying and then re-copying new props back
                   */
                  instance.$update = function(n){
                      shallowClearAndCopy(n, instance);
                      return instance;
                  };
  
  
                  /**
                   * Creates a copy by taking the raw data values and by
                   * creating a new instance of the model.
                   */
                  instance.$copy = function(){
                    // get the raw data of the model
                    var rawData = angular.toJson(this);
  
                    // ..then wrap it into a new instance to create a clone
                    return new Model(angular.fromJson(rawData));
                  };
  
                  // Create a copy of the value last so we get all the goodies,
                  // like default values and whatnot.
                  instance.$commit();
              }