diff --git src/wp-admin/js/customize-controls.js src/wp-admin/js/customize-controls.js
index 0ea60ce..851eaf3 100644
--- src/wp-admin/js/customize-controls.js
+++ src/wp-admin/js/customize-controls.js
@@ -1,6 +1,6 @@
 /* globals _wpCustomizeHeader, _wpMediaViewsL10n */
 (function( exports, $ ){
-	var bubbleChildValueChanges, Container, focus, isKeydownButNotEnterEvent, areElementListsEqual, api = wp.customize;
+	var bubbleChildValueChanges, Container, focus, isKeydownButNotEnterEvent, areElementListsEqual, stableSort, api = wp.customize;
 
 	// @todo Move private helper functions to wp.customize.utils so they can be unit tested
 
@@ -78,6 +78,23 @@
 	};
 
 	/**
+	 * Stable sort for Panels, Sections, and Controls.
+	 *
+	 * If a.priority() === b.priority(), then sort by their respective params.instanceNumber.
+	 *
+	 * @param {(wp.customize.Panel|wp.customize.Section|wp.customize.Control)} a
+	 * @param {(wp.customize.Panel|wp.customize.Section|wp.customize.Control)} b
+	 * @returns {Number}
+	 */
+	stableSort = function ( a, b ) {
+		if ( a.priority() === b.priority() && typeof a.params.instanceNumber === 'number' && typeof b.params.instanceNumber === 'number' ) {
+			return a.params.instanceNumber - b.params.instanceNumber;
+		} else {
+			return a.priority() - b.priority();
+		}
+	};
+
+	/**
 	 * Return whether the supplied Event object is for a keydown event but not the Enter key.
 	 *
 	 * @param {jQuery.Event} event
@@ -176,9 +193,7 @@
 					children.push( child );
 				}
 			} );
-			children.sort( function ( a, b ) {
-				return a.priority() - b.priority();
-			} );
+			children.sort( stableSort );
 			return children;
 		},
 
@@ -1952,9 +1967,7 @@
 			} );
 
 			// Sort the root panels and sections
-			rootNodes.sort( function ( a, b ) {
-				return a.priority() - b.priority();
-			} );
+			rootNodes.sort( stableSort );
 			rootContainers = _.pluck( rootNodes, 'container' );
 			appendContainer = $( '#customize-theme-controls' ).children( 'ul' ); // @todo This should be defined elsewhere, and to be configurable
 			if ( ! areElementListsEqual( rootContainers, appendContainer.children() ) ) {
diff --git src/wp-includes/class-wp-customize-control.php src/wp-includes/class-wp-customize-control.php
index dcebb0f..a2df83f 100644
--- src/wp-includes/class-wp-customize-control.php
+++ src/wp-includes/class-wp-customize-control.php
@@ -7,6 +7,27 @@
  * @since 3.4.0
  */
 class WP_Customize_Control {
+
+	/**
+	 * Incremented with each new class instantiation, then stored in $instance_number.
+	 *
+	 * Used when sorting two instances whose priorities are equal.
+	 *
+	 * @since 4.1.0
+	 * @access protected
+	 * @var int
+	 */
+	protected static $instance_count = 0;
+
+	/**
+	 * Order in which this instance was created in relation to other instances.
+	 *
+	 * @since 4.1.0
+	 * @access public
+	 * @var int
+	 */
+	public $instance_number;
+
 	/**
 	 * @access public
 	 * @var WP_Customize_Manager
@@ -127,6 +148,8 @@ class WP_Customize_Control {
 		if ( empty( $this->active_callback ) ) {
 			$this->active_callback = array( $this, 'active_callback' );
 		}
+		self::$instance_count += 1;
+		$this->instance_number = self::$instance_count;
 
 		// Process settings.
 		if ( empty( $this->settings ) ) {
@@ -218,13 +241,14 @@ class WP_Customize_Control {
 			$this->json['settings'][ $key ] = $setting->id;
 		}
 
-		$this->json['type']        = $this->type;
-		$this->json['priority']    = $this->priority;
-		$this->json['active']      = $this->active();
-		$this->json['section']     = $this->section;
-		$this->json['content']     = $this->get_content();
-		$this->json['label']       = $this->label;
+		$this->json['type'] = $this->type;
+		$this->json['priority'] = $this->priority;
+		$this->json['active'] = $this->active();
+		$this->json['section'] = $this->section;
+		$this->json['content'] = $this->get_content();
+		$this->json['label'] = $this->label;
 		$this->json['description'] = $this->description;
+		$this->json['instanceNumber'] = $this->instance_number; // note: camelCase for JS
 	}
 
 	/**
diff --git src/wp-includes/class-wp-customize-manager.php src/wp-includes/class-wp-customize-manager.php
index 371ea90..987edc6 100644
--- src/wp-includes/class-wp-customize-manager.php
+++ src/wp-includes/class-wp-customize-manager.php
@@ -856,28 +856,27 @@ final class WP_Customize_Manager {
 	 * @since 4.1.0
 	 */
 	public function render_control_templates() {
-		foreach( $this->registered_control_types as $control_type ) {
+		foreach ( $this->registered_control_types as $control_type ) {
 			$control = new $control_type( $this, 'temp', array() );
 			$control->print_template();
 		}
 	}
 
-    /** 
-	 * Helper function to compare two objects by priority.
+	/**
+	 * Helper function to compare two objects by priority, ensuring sort stability via instance_number.
 	 *
 	 * @since 3.4.0
 	 *
-	 * @param object $a Object A.
-	 * @param object $b Object B.
+	 * @param {WP_Customize_Panel|WP_Customize_Section|WP_Customize_Control} $a Object A.
+	 * @param {WP_Customize_Panel|WP_Customize_Section|WP_Customize_Control} $b Object B.
 	 * @return int
 	 */
 	protected final function _cmp_priority( $a, $b ) {
-		$ap = $a->priority;
-		$bp = $b->priority;
-
-		if ( $ap == $bp )
-			return 0;
-		return ( $ap > $bp ) ? 1 : -1;
+		if ( $a->priority === $b->priority ) {
+			return $a->instance_number - $a->instance_number;
+		} else {
+			return $a->priority - $b->priority;
+		}
 	}
 
 	/**
@@ -891,8 +890,8 @@ final class WP_Customize_Manager {
 	 */
 	public function prepare_controls() {
 
-		$this->controls = array_reverse( $this->controls );
 		$controls = array();
+		uasort( $this->controls, array( $this, '_cmp_priority' ) );
 
 		foreach ( $this->controls as $id => $control ) {
 			if ( ! isset( $this->sections[ $control->section ] ) || ! $control->check_capabilities() ) {
@@ -905,8 +904,6 @@ final class WP_Customize_Manager {
 		$this->controls = $controls;
 
 		// Prepare sections.
-		// Reversing makes uasort sort by time added when conflicts occur.
-		$this->sections = array_reverse( $this->sections );
 		uasort( $this->sections, array( $this, '_cmp_priority' ) );
 		$sections = array();
 
@@ -930,8 +927,6 @@ final class WP_Customize_Manager {
 		$this->sections = $sections;
 
 		// Prepare panels.
-		// Reversing makes uasort sort by time added when conflicts occur.
-		$this->panels = array_reverse( $this->panels );
 		uasort( $this->panels, array( $this, '_cmp_priority' ) );
 		$panels = array();
 
diff --git src/wp-includes/class-wp-customize-panel.php src/wp-includes/class-wp-customize-panel.php
index 201c4b9..af8f243 100644
--- src/wp-includes/class-wp-customize-panel.php
+++ src/wp-includes/class-wp-customize-panel.php
@@ -11,6 +11,26 @@
 class WP_Customize_Panel {
 
 	/**
+	 * Incremented with each new class instantiation, then stored in $instance_number.
+	 *
+	 * Used when sorting two instances whose priorities are equal.
+	 *
+	 * @since 4.1.0
+	 * @access protected
+	 * @var int
+	 */
+	protected static $instance_count = 0;
+
+	/**
+	 * Order in which this instance was created in relation to other instances.
+	 *
+	 * @since 4.1.0
+	 * @access public
+	 * @var int
+	 */
+	public $instance_number;
+
+	/**
 	 * WP_Customize_Manager instance.
 	 *
 	 * @since 4.0.0
@@ -128,6 +148,8 @@ class WP_Customize_Panel {
 		if ( empty( $this->active_callback ) ) {
 			$this->active_callback = array( $this, 'active_callback' );
 		}
+		self::$instance_count += 1;
+		$this->instance_number = self::$instance_count;
 
 		$this->sections = array(); // Users cannot customize the $sections array.
 
@@ -185,6 +207,7 @@ class WP_Customize_Panel {
 		$array = wp_array_slice_assoc( (array) $this, array( 'title', 'description', 'priority', 'type' ) );
 		$array['content'] = $this->get_content();
 		$array['active'] = $this->active();
+		$array['instanceNumber'] = $this->instance_number; // camelCase
 		return $array;
 	}
 
diff --git src/wp-includes/class-wp-customize-section.php src/wp-includes/class-wp-customize-section.php
index 3553285..a90feb5 100644
--- src/wp-includes/class-wp-customize-section.php
+++ src/wp-includes/class-wp-customize-section.php
@@ -11,6 +11,26 @@
 class WP_Customize_Section {
 
 	/**
+	 * Incremented with each new class instantiation, then stored in $instance_number.
+	 *
+	 * Used when sorting two instances whose priorities are equal.
+	 *
+	 * @since 4.1.0
+	 * @access protected
+	 * @var int
+	 */
+	protected static $instance_count = 0;
+
+	/**
+	 * Order in which this instance was created in relation to other instances.
+	 *
+	 * @since 4.1.0
+	 * @access public
+	 * @var int
+	 */
+	public $instance_number;
+
+	/**
 	 * WP_Customize_Manager instance.
 	 *
 	 * @since 3.4.0
@@ -137,6 +157,8 @@ class WP_Customize_Section {
 		if ( empty( $this->active_callback ) ) {
 			$this->active_callback = array( $this, 'active_callback' );
 		}
+		self::$instance_count += 1;
+		$this->instance_number = self::$instance_count;
 
 		$this->controls = array(); // Users cannot customize the $controls array.
 
@@ -194,6 +216,7 @@ class WP_Customize_Section {
 		$array = wp_array_slice_assoc( (array) $this, array( 'title', 'description', 'priority', 'panel', 'type' ) );
 		$array['content'] = $this->get_content();
 		$array['active'] = $this->active();
+		$array['instanceNumber'] = $this->instance_number; // camelCase
 		return $array;
 	}
 
