docs: function (key, value, options) {
  
                      if (_.isNumber(key)) {
                          key = String(key);
                      }
  
                      if (_.isString(key)) {
                          var attributes = {};
                          attributes[key] = value;
                      } else {
                          options = value;
                          attributes = key;
                      }
  
                      options = options || {silent: false, unset: false, force: false};
  
                      // for un-setting attributes
                      if (options.unset) {
                          for (key in attributes) {
                              if (attributes.hasOwnProperty(key)) {
                                  attributes[key] = void 0;
                              }
                          }
                      }
  
                      var changedAttributes = {},
                          changedAttributesCount = 0,
                          now = this.$,
                          val, prev;
  
                      for (key in attributes) {
                          if (attributes.hasOwnProperty(key)) {
                              // get the value
                              val = attributes[key];
                              // unset attribute or change it ...
                              if (options.unset === true) {
                                  prev = now[key];
                                  delete now[key];
                                  changedAttributes[key] = undefined;
                                  changedAttributesCount++;
                                  this.$previousAttributes[key] = prev;
                              } else {
                                  if (options.force || !isEqual(now[key], attributes[key])) {
                                      prev = options.initial ? null : now[key];
                                      this.$previousAttributes[key] = prev;
                                      now[key] = attributes[key];
                                      changedAttributes[key] = now[key];
  
                                      changedAttributesCount++;
                                  }
                              }
                          }
                      }
  
                      var commitMethod;
                      if (changedAttributesCount) {
                          for (key in changedAttributes) {
                              if (changedAttributes.hasOwnProperty(key)) {
                                  commitMethod = this['_commit' + key.charAt(0).toUpperCase() + key.substr(1)];
  
                                  if (commitMethod instanceof Function) {
                                      // call method
  
                                      if (commitMethod.call(this, now[key], this.$previousAttributes[key], options) === false) {
                                          // false returned rollback
                                          changedAttributesCount--;
                                          now[key] = this.$previousAttributes[key];
                                      }
                                  }
                              }
                          }
  
                          if (changedAttributesCount) {
                              this._commitChangedAttributes(changedAttributes, options);
                              if (!options.silent) {
                                  for (key in changedAttributes) {
                                      if (changedAttributes.hasOwnProperty(key)) {
                                          this.trigger('change:' + key, changedAttributes[key], this);
                                      }
                                  }
                                  this.trigger('change', changedAttributes, this);
                              }
                          }
  
                      }
  
                      return this;
                  }