We didn't want to add another framework to achieve that so we abstracted it away in a base model class.
Here's how you declare and use it (available as a gist):
// Declaration
window.app.viewer.Model.GallerySection = window.app.Model.BaseModel.extend({
  nestedTypes: {
    background: window.app.viewer.Model.Image,
    images: window.app.viewer.Collection.MediaCollection
  }
});
// Usage
var gallery = new window.app.viewer.Model.GallerySection({
    background: { url: 'http://example.com/example.jpg' },
    images: [
        { url: 'http://example.com/1.jpg' },
        { url: 'http://example.com/2.jpg' },
        { url: 'http://example.com/3.jpg' }
    ],
    title: 'Wow'
}); // (fetch will work equally well)
console.log(gallery.get('background')); // window.app.viewer.Model.Image
console.log(gallery.get('images')); // window.app.viewer.Collection.MediaCollection
console.log(gallery.get('title')); // plain string
It works equally well with set and toJSON.
And here's BaseModel:
window.app.Model.BaseModel = Backbone.Model.extend({
  constructor: function () {
    if (this.nestedTypes) {
      this.checkNestedTypes();
    }
    Backbone.Model.apply(this, arguments);
  },
  set: function (key, val, options) {
    var attrs;
    /* jshint -W116 */
    /* jshint -W030 */
    // Code below taken from Backbone 1.0 to allow different parameter styles
    if (key == null) return this;
    if (typeof key === 'object') {
      attrs = key;
      options = val;
    } else {
      (attrs = {})[key] = val;
    }
    options || (options = {});
    // Code above taken from Backbone 1.0 to allow different parameter styles
    /* jshint +W116 */
    /* jshint +W030 */
    // What we're trying to do here is to instantiate Backbone models and collections
    // with types defined in this.nestedTypes, and use them instead of plain objects in attrs.
    if (this.nestedTypes) {
      attrs = this.mapAttributes(attrs, this.deserializeAttribute);
    }
    return Backbone.Model.prototype.set.call(this, attrs, options);
  },
  toJSON: function () {
    var json = Backbone.Model.prototype.toJSON.apply(this, arguments);
    if (this.nestedTypes) {
      json = this.mapAttributes(json, this.serializeAttribute);
    }
    return json;
  },
  mapAttributes: function (attrs, transform) {
    transform = _.bind(transform, this);
    var result = {};
    _.each(attrs, function (val, key) {
      result[key] = transform(val, key);
    }, this);
    return result;
  },
  serializeAttribute: function (val, key) {
    var NestedType = this.nestedTypes[key];
    if (!NestedType) {
      return val;
    }
    if (_.isNull(val) || _.isUndefined(val)) {
      return val;
    }
    return val.toJSON();
  },
  deserializeAttribute: function (val, key) {
    var NestedType = this.nestedTypes[key];
    if (!NestedType) {
      return val;
    }
    var isCollection = this.isTypeASubtypeOf(NestedType, Backbone.Collection),
        child;
    if (val instanceof Backbone.Model || val instanceof Backbone.Collection) {
      child = val;
    } else if (!isCollection && (_.isNull(val) || _.isUndefined(val))) {
      child = null;
    } else {
      child = new NestedType(val);
    }
    var prevChild = this.get(key);
    // Return existing model if it is equal to child's attributes
    if (!isCollection && child && prevChild && _.isEqual(prevChild.attributes, child.attributes)) {
      return prevChild;
    }
    return child;
  },
  isTypeASubtypeOf: function (DerivedType, BaseType) {
    // Go up the tree, using Backbone's __super__.
    // This is not exactly encouraged by the docs, but I found no other way.
    if (_.isUndefined(DerivedType['__super__'])) {
      return false;
    }
    var ParentType = DerivedType['__super__'].constructor;
    if (ParentType === BaseType) {
      return true;
    }
    return this.isTypeASubtypeOf(ParentType, BaseType);
  },
  checkNestedTypes: function () {
    _.each(this.nestedTypes, function (val, key) {
      if (!_.isFunction(val)) {
        console.log('Not a function:', val);
        throw new Error('Invalid nestedTypes declaration for key ' + key + ': expected a function');
      }
    });
  },
}