private object UnwrapParamValue(JToken parameterToken, Type parameterType, IPluginManager pluginManager)
        {
            var defaultValue = new Func <object>(() => parameterToken.ToObject(parameterType));
            var jobject      = parameterToken as JObject;

            if (jobject != null)
            {
                if (jobject.Type == JTokenType.Object)
                {
                    if (parameterType == typeof(object))
                    {
                        return(defaultValue());
                    }

                    if (parameterType == typeof(string))
                    {
                        // If the parameter is a JSON object, but the parameter type is string return the raw JSON.
                        return(jobject.ToString());
                    }

                    JToken typeValue, payload;
                    if (!jobject.TryGetValue("__type__", out typeValue) || !jobject.TryGetValue("__payload__", out payload))
                    {
                        return(defaultValue());
                    }

                    var payloadJObj = payload as JObject;
                    if (payloadJObj == null)
                    {
                        return(defaultValue());
                    }

                    if (payloadJObj.Type != JTokenType.Object)
                    {
                        return(defaultValue());
                    }

                    if ((string)typeValue != "reference")
                    {
                        return(defaultValue());
                    }

                    JToken dynamicPluginGuid;
                    if (!payloadJObj.TryGetValue("id", out dynamicPluginGuid))
                    {
                        return(defaultValue());
                    }

                    var dynamicPlugin = pluginManager.GetLocalPlugin((string)dynamicPluginGuid);
                    if (dynamicPlugin != null)
                    {
                        return(dynamicPlugin.NativeObject);
                    }

                    throw new NullReferenceException("Failed to map Javascript parameter to native dynamic plugin object ");
                }
            }

            var jarray = parameterToken as JArray;

            if (jarray != null)
            {
                if (jarray.Type != JTokenType.Array)
                {
                    return(defaultValue());
                }

                if (parameterType == typeof(object))
                {
                    return(defaultValue());
                }

                var elementType = parameterType.GetElementType();
                if (elementType == null)
                {
                    if (!typeof(JArray).IsAssignableFrom(parameterType) && !typeof(Array).IsAssignableFrom(parameterType))
                    {
                        return(parameterType == typeof(string) ? jarray.ToString() : null);
                    }

                    if (typeof(JArray).IsAssignableFrom(parameterType))
                    {
                        return(defaultValue());
                    }
                }

                elementType = elementType ?? typeof(object);
                var nativeArray = Array.CreateInstance(elementType, jarray.Count);
                for (var i = 0; i < jarray.Count; i++)
                {
                    nativeArray.SetValue(Convert.ChangeType(UnwrapParamValue(jarray[i], elementType, pluginManager), elementType), i);
                }

                return(nativeArray);
            }

            return(defaultValue());
        }