function Address(data, network, type, multisigType) {
  /* jshint maxcomplexity: 12 */
  /* jshint maxstatements: 20 */

  if (!(this instanceof Address)) {
    return new Address(data, network, type);
  }

  if (_.isArray(data) && _.isNumber(network)) {
    return Address.createMultisig(data, network, type, false, multisigType);
  }

  if (data instanceof Address) {
    // Immutable instance
    return data;
  }

  $.checkArgument(data, 'First argument is required, please include address data.', 'guide/address.html');

  if (network && !Networks.get(network)) {
    throw new TypeError('Second argument must be "livenet" or "testnet".');
  }

  if (type && (
    type !== Address.PayToPublicKeyHash
    && type !== Address.PayToScriptHash
    && type !== Address.PayToWitnessPublicKeyHash
    && type !== Address.PayToWitnessScriptHash)) {
    throw new TypeError('Third argument must be "pubkeyhash", "scripthash", "witnesspubkeyhash", or "witnessscripthash".');
  }

  var info = this._classifyArguments(data, network, type);

  // set defaults if not set
  info.network = info.network || Networks.get(network) || Networks.defaultNetwork;
  info.type = info.type || type || Address.PayToPublicKeyHash;

  JSUtil.defineImmutable(this, {
    hashBuffer: info.hashBuffer,
    network: info.network,
    type: info.type
  });

  return this;
}
Instantiate an address from an address String or Buffer, a public key or script hash Buffer,
or an instance of {@link PublicKey} or {@link Script}.

This is an immutable class, and if the first parameter provided to this constructor is an
`Address` instance, the same argument will be returned.

An address has two key properties: `network` and `type`. The type is one of
`Address.PayToPublicKeyHash` (value is the `'pubkeyhash'` string),
`Address.PayToScriptHash` (the string `'scripthash'`),
`Address.PayToWitnessPublicKeyHash` (the string `'witnesspubkeyhash'`),
or `Address.PayToWitnessScriptHash` (the string `'witnessscripthash'`).
The network is an instance of {@link Network}.
You can quickly check whether an address is of a given kind by using the methods
`isPayToPublicKeyHash`, `isPayToScriptHash`, `isPayToWitnessPublicKeyHash`,
and `isPayToWitnessScriptHash`.

@example
```javascript
// validate that an input field is valid
var error = Address.getValidationError(input, 'testnet');
if (!error) {
  var address = Address(input, 'testnet');
} else {
  // invalid network or checksum (typo?)
  var message = error.messsage;
}

// get an address from a public key
var address = Address(publicKey, 'testnet').toString();
```

@param {*} data - The encoded data in various formats
@param {Network|String|number=} network - The network: 'livenet' or 'testnet'
@param {string=} type - The type of address: 'scripthash', 'pubkeyhash', witnessscripthash or 'witnesspubkeyhash'
@param {string=} multisigType - The type of multisig: 'scripthash' or 'witnessscripthash'
@returns {Address} A new valid and frozen instance of an Address
@constructor